﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace ExcelConverter
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        private const int SAVE_CONTENT_COUNT = 2;
        private const string CONFIG_PATH = "./ec_config.ini";
        
        public static Window Instance;

        private static Encoding s_encoding = new UTF8Encoding(false);
        private readonly List<string> _cachedPathList = new List<string>();
        public MainWindow()
        {
            Instance = this;
            InitializeComponent();

            if (File.Exists(CONFIG_PATH))
            {
                var pathPairs = File.ReadAllLines(CONFIG_PATH, s_encoding);
                for (var i = 0; i < pathPairs.Length; i++)
                {
                    var pairStr = pathPairs[i];
                    var pathPair = pairStr.Split('|');
                    if (pathPair.Length == SAVE_CONTENT_COUNT)
                    {
                        if (!_cachedPathList.Contains(pairStr))
                        {
                            _cachedPathList.Add(pairStr);
                        }
                    }
                }
                RefreshCachedPathMenu();
            }
            ApplyPath(0);
        }
        private void RefreshCachedPathMenu()
        {
            SavedPath.Items.Clear();
            for (var i = 0; i < _cachedPathList.Count; i++)
            {
                var index = i;
                var path = _cachedPathList[i];
                //选项
                var pathMenuItem = new MenuItem();
                pathMenuItem.Header = path.Replace("|", "\n") + " (右键选择)";
                pathMenuItem.FontSize = 22;
                pathMenuItem.Background = new SolidColorBrush(Colors.LightGray);
                pathMenuItem.MouseUp += (sender, args) =>
                {
                    if (ApplyPath(index))
                    {
                        //失焦
                        SavedPath.IsSubmenuOpen = false;
                        //把应用的放在第一位
                        if (index != 0)
                        {
                            (_cachedPathList[index], _cachedPathList[0]) = (_cachedPathList[0], _cachedPathList[index]);
                            RefreshCachedPathMenu();
                        }
                    }
                };
                //移除
                {
                    var deleteMenuItem = new MenuItem();
                    deleteMenuItem.Header = "移除";
                    deleteMenuItem.FontSize = 22;
                    deleteMenuItem.Background = new SolidColorBrush(Colors.Salmon);
                    deleteMenuItem.Click += (sender, args) =>
                    {
                        _cachedPathList.RemoveAt(index);
                        RefreshCachedPathMenu();
                    };
                    pathMenuItem.Items.Add(deleteMenuItem);
                }
                SavedPath.Items.Add(pathMenuItem);
            }
            //清空
            {
                var clearMenuItem = new MenuItem();
                clearMenuItem.Header = "清空";
                clearMenuItem.FontSize = 22;
                clearMenuItem.Background = new SolidColorBrush(Colors.Salmon);
                clearMenuItem.Click += (sender, args) =>
                {
                    _cachedPathList.Clear();
                    RefreshCachedPathMenu();
                };
                SavedPath.Items.Add(clearMenuItem);
            }
            SaveCachedPath();
        }
        private void SaveCachedPath()
        {
            var list = new List<string>(_cachedPathList);
            File.WriteAllText(CONFIG_PATH, string.Join("\n", list), s_encoding);
        }
        public static string GetRelativePath(string path)
        {
            var relativeTo = Directory.GetCurrentDirectory();
            path = Path.GetFullPath(path);
            if (path == relativeTo) return "./";
            var oldPath = path;
            // 确保两个路径都是以目录分隔符结束
            if (!relativeTo.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            {
                relativeTo += Path.DirectorySeparatorChar;
            }
            if (!File.Exists(oldPath) && !path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
            {
                path += Path.DirectorySeparatorChar;
            }
            // 将两个路径转换为Uri对象
            Uri relativeToUri = new Uri(relativeTo);
            Uri pathUri = new Uri(path);
            // 计算两个Uri之间的相对Uri
            Uri relativeUri = relativeToUri.MakeRelativeUri(pathUri);
            // 将相对Uri转换回相对路径字符串
            string relativePath = Uri.UnescapeDataString(relativeUri.ToString());
            return relativePath;
        }
        private void AddCachedPath(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(_jsonDestPath)) return;
            
            var pathPair = $"{_defineFilePath}|{_jsonDestPath}";
            if (!_cachedPathList.Contains(pathPair))
            {
                _cachedPathList.Insert(0, pathPair);
                RefreshCachedPathMenu();
            }
            ShowTip("已保存地址");
        }
        //保存快捷键
        private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
        {
            if ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) != 0 && e.Key == Key.S)
            {
                AddCachedPath(default, default);
            }
        }
        //应用路径
        private bool ApplyPath(int index)
        {
            if (index >= _cachedPathList.Count) return false;
            var pathPair = _cachedPathList[index].Split('|');
            if (pathPair.Length == SAVE_CONTENT_COUNT)
            {
                //别名文件路径
                var defineFilePath = pathPair[0];
                _defineFilePath = File.Exists(defineFilePath) ? defineFilePath : null;
                //输出位置
                var jsonDestPath = pathPair[1];
                _jsonDestPath = Directory.Exists(jsonDestPath) ? jsonDestPath : null;
                RefreshDestPath();
                RefreshDefineFilePath();
                return true;
            }
            return false;
        }
        
        /// <summary>
        /// 显示提示
        /// </summary>
        public static void ShowTip(string msg)
        {
            MessageBox.Show(msg, "Tip", MessageBoxButton.OK);
        }
        /// <summary>
        /// 显示提示
        /// </summary>
        public static ProgressWindow ShowProgress()
        {
            var window = new ProgressWindow();
            window.Owner = Instance;
            window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            window.WindowStyle = WindowStyle.None;
            window.ResizeMode = ResizeMode.NoResize;
            window.SetProgress(0f);
            window.SetText("");
            window.Show();
            return window;
        }

        private readonly HashSet<string> m_srcPathSet = new HashSet<string>();
        private void OnSrcDrop(object sender, DragEventArgs e)
        {
            var files = (string[]) e.Data.GetData(DataFormats.FileDrop);
            for (var i = 0; i < files.Length; i++)
            {
                var path = files[i];
                if (File.Exists(path) && (path.EndsWith(".xlsx") || path.EndsWith(".xls")))
                {
                    path = GetRelativePath(path);
                    m_srcPathSet.Add(path);
                }
            }
            if (m_srcPathSet.Count == 0) return;
            RefreshSrcList();
        }

        private string _jsonDestPath;
        private string _defineFilePath;
        private void OnJsonDestDrop(object sender, DragEventArgs e)
        {
            var files = (string[]) e.Data.GetData(DataFormats.FileDrop);
            for (var i = 0; i < files.Length; i++)
            {
                var path = files[i];
                if (Directory.Exists(path))
                {
                    path = GetRelativePath(path);
                    _jsonDestPath = path;
                    RefreshDestPath();
                    return;
                }
            }
            ShowTip("无效文件夹!");
        }
        private void OnDefineFileDrop(object sender, DragEventArgs e)
        {
            var files = (string[]) e.Data.GetData(DataFormats.FileDrop);
            for (var i = 0; i < files.Length; i++)
            {
                var path = files[i];
                if (File.Exists(path) && (path.EndsWith(".xlsx") || path.EndsWith(".xls")))
                {
                    path = GetRelativePath(path);
                    _defineFilePath = path;
                    RefreshDefineFilePath();
                    return;
                }
            }
        }
        
        private async void OnConvertToJsonClick(object sender, RoutedEventArgs e)
        {
            if (m_srcPathSet.Count == 0)
            {
                ShowTip("未添加文件!");
                return;
            }
            if (string.IsNullOrEmpty(_jsonDestPath))
            {
                ShowTip("未添加Json目标文件夹!");
                return;
            }
            var result = Converter.GetDefineMap(_defineFilePath);
            if (!string.IsNullOrEmpty(result.reason))
            {
                ShowTip(result.reason);
                return;
            }

            EConvertType type = 0;
            if (ClientToggle.IsChecked == true) type |= EConvertType.Client;
            if (ServerToggle.IsChecked == true) type |= EConvertType.Server;
            var destPath = Path.GetFullPath(_jsonDestPath);
            var pathArr = m_srcPathSet.ToArray();
            var pathCount = pathArr.Length;
            var progressWindow = ShowProgress();
            var successCount = 0;
            for (var i = 0; i < pathCount; i++)
            {
                var path = pathArr[i];
                var lastDivIndex = path.LastIndexOf('\\');
                var fileName = path.Substring(lastDivIndex + 1, path.Length - lastDivIndex - 1 - 5);
                progressWindow.SetText($"正在打开表格: {fileName}");
                path = Path.GetFullPath(path);
                await Task.Delay(5);
                var task = Converter.Convert(path, destPath, type, result.defineMap, 
                    (sheetName, curLine, totalLine) =>
                    {
                        var p = (float) curLine / totalLine;
                        if (totalLine > 0)
                        {
                            progressWindow.SetProgress(p);
                            progressWindow.SetText($"{sheetName}: {curLine} / {totalLine}");
                        }
                    });
                await task;
                if (string.IsNullOrEmpty(task.Result))
                {
                    successCount++;
                }
                else
                {
                    ShowTip(task.Result);
                }
            }
            progressWindow.Hide();
            ShowTip($"成功转换 [{successCount}/{m_srcPathSet.Count}]!");
        }
        private void ClearSrcFile(object sender, RoutedEventArgs e)
        {
            m_srcPathSet.Clear();
            RefreshSrcList();
        }
        private void ClearDefineFile(object sender, RoutedEventArgs e)
        {
            _defineFilePath = null;
            RefreshDefineFilePath();
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            SaveCachedPath();
        }

        private void RefreshSrcList()
        {
            SrcScroll.ScrollToVerticalOffset(1);
            if (m_srcPathSet.Count > 0)
            {
                SrcArea.Content = "待转列表: \n";
                SrcArea.HorizontalContentAlignment = HorizontalAlignment.Left;
                SrcArea.Content += string.Join("\n", m_srcPathSet);
                SrcArea.FontSize = 20;
            }
            else
            {
                SrcArea.Content = "源文件";
                SrcArea.HorizontalContentAlignment = HorizontalAlignment.Center;
                SrcArea.FontSize = 50;
            }
        }
        private void RefreshDestPath()
        {
            if (!string.IsNullOrEmpty(_jsonDestPath))
            {
                JsonDestArea.Text = "Json文件夹: \n" + _jsonDestPath;
                JsonDestArea.FontSize = 22;
            }
            else
            {
                JsonDestArea.Text = "Json文件夹";
                JsonDestArea.FontSize = 50;
            }
        }
        private void RefreshDefineFilePath()
        {
            if (!string.IsNullOrEmpty(_defineFilePath))
            {
                DefineFileArea.Text = _defineFilePath;
                DefineFileArea.FontSize = 25;
            }
            else
            {
                DefineFileArea.Text = "专用别名文件";
                DefineFileArea.FontSize = 30;
            }
        }
        
        private void OnMouseRightButtonUp_Json(object sender, MouseButtonEventArgs e)
        {
            if (!string.IsNullOrEmpty(_jsonDestPath) && Directory.Exists(_jsonDestPath))
            {
                Process.Start(Path.GetFullPath(_jsonDestPath));
            }
        }
        private void OnMouseRightButtonUp_Define(object sender, MouseButtonEventArgs e)
        {
            if (!string.IsNullOrEmpty(_defineFilePath) && File.Exists(_defineFilePath))
            {
                Process.Start(Path.GetFullPath(_defineFilePath));
            }
        }
    }
}